
#include <string.h>
#include "Entity.h"
#include "MQTTNode.h"
#include "MQTT/MQTTError.h"
#include "Core/Interface.h"
#include "Core/Utils/List.h"

static void destroyMqttSubListHandlerList(ListHead *list) {

    MQTTSubHandlerNode *node = NULL, *next = NULL;
    AIOT_LIST_FOR_EACH_ENTRY_SAFE(node, next, list, linkedNode, MQTTSubHandlerNode) {
        aiotListDel(&node->linkedNode);
        getSystemInterface()->memFree(node);
    }
}

static int32_t insertMqttHandlerList(MQTTEntity *entity, MQTTSubNode *subNode, RecvHandler handler, void *context) {

    MQTTSubHandlerNode *node = NULL;
    AIOT_LIST_FOR_EACH_ENTRY(node, &subNode->handleList, linkedNode, MQTTSubHandlerNode) {
        if (node->handler == handler) {
            /** exist handler, replace userdata */
            node->context = context;
            return aiotSuccess;
        }
    }

    if (&node->linkedNode == &subNode->handleList) {
        /** new handler */
        node = getSystemInterface()->memMalloc(sizeof(MQTTSubHandlerNode));
        if (node == NULL) {
            return memoryMallocFailed;
        }

        memset(node, 0, sizeof(MQTTSubHandlerNode));
        initialAiotListHead(&node->linkedNode);
        node->handler = handler;
        node->context = context;

        aiotListAddTail(&node->linkedNode, &subNode->handleList);
    }

    return aiotSuccess;
}

void remoteTopicAliasList(MQTTEntity *entity) {

    MQTTTopicAliasNode *node = NULL, *next = NULL;
    AIOT_LIST_FOR_EACH_ENTRY_SAFE(node, next, &entity->rxTopicAliasList, linkedNode,MQTTTopicAliasNode) {
        aiotListDel(&node->linkedNode);
        getSystemInterface()->memFree(node->topic);
        getSystemInterface()->memFree(node);
    }

    AIOT_LIST_FOR_EACH_ENTRY_SAFE(node, next, &entity->txTopicAliasList, linkedNode,MQTTTopicAliasNode) {

        aiotListDel(&node->linkedNode);
        getSystemInterface()->memFree(node->topic);
        getSystemInterface()->memFree(node);
    }
}

void destroyMqttSubList(MQTTEntity *entity) {

    MQTTSubNode *node = NULL, *next = NULL;
    AIOT_LIST_FOR_EACH_ENTRY_SAFE(node, next, &entity->subList, linkedNode, MQTTSubNode) {
        aiotListDel(&node->linkedNode);
        destroyMqttSubListHandlerList(&node->handleList);
        getSystemInterface()->memFree(node->topic);
        getSystemInterface()->memFree(node);
    }
}

void destroyMqttPubList(MQTTEntity *entity) {

    MQTTPubNode *node = NULL, *next = NULL;
    AIOT_LIST_FOR_EACH_ENTRY_SAFE(node, next, &entity->pubList,linkedNode, MQTTPubNode) {
        aiotListDel(&node->linkedNode);
        getSystemInterface()->memFree(node->packet);
        getSystemInterface()->memFree(node);
    }
}

void destroyMqttProcessDataList(MQTTEntity *entity) {

    MQTTProcessDataNode *node = NULL, *next = NULL;
    AIOT_LIST_FOR_EACH_ENTRY_SAFE(node, next, &entity->processList,linkedNode, MQTTProcessDataNode) {
        aiotListDel(&node->linkedNode);
        getSystemInterface()->memFree(node);
    }
}

int32_t insertMqttSubList(MQTTEntity *entity, MQTTBuffer *topic,RecvHandler handler, void *context) {

    int32_t res = aiotSuccess;
    MQTTSubNode *node = NULL;
    AIOT_LIST_FOR_EACH_ENTRY(node, &entity->subList, linkedNode, MQTTSubNode) {

        if ((strlen(node->topic) == topic->len) && memcmp(node->topic, topic->buffer, topic->len) == 0) {
            if (handler != NULL) {
                return insertMqttHandlerList(entity, node, handler, context);
            } else {
                return aiotSuccess;
            }
        }
    }

    if (&node->linkedNode == &entity->subList) {
        /** new topic */
        node = getSystemInterface()->memMalloc(sizeof(MQTTSubNode));
        if (node == NULL) {
            return memoryMallocFailed;
        }

        memset(node, 0, sizeof(MQTTSubNode));
        initialAiotListHead(&node->linkedNode);
        initialAiotListHead(&node->handleList);

        node->topic = getSystemInterface()->memMalloc(topic->len + 1);
        if (node->topic == NULL) {
            getSystemInterface()->memFree(node);
            return memoryMallocFailed;
        }

        memset(node->topic, 0, topic->len + 1);
        memcpy(node->topic, topic->buffer, topic->len);

        if (handler != NULL) {
            res = insertMqttHandlerList(entity, node, handler, context);
            if (res < aiotSuccess) {
                getSystemInterface()->memFree(node->packet);
                getSystemInterface()->memFree(node->topic);
                getSystemInterface()->memFree(node);
                return res;
            }
        }
        node->sendAt = getSystemInterface()->getTimestamp();
        aiotListAddTail(&node->linkedNode, &entity->subList);
    }

    return res;
}

void removeMqttSubListHandler(MQTTEntity *entity, MQTTBuffer *topic, RecvHandler handler) {

    MQTTSubNode *node = NULL;
    MQTTSubHandlerNode *handler_node = NULL, *handler_next = NULL;
    AIOT_LIST_FOR_EACH_ENTRY(node, &entity->subList, linkedNode, MQTTSubNode) {
        if ((strlen(node->topic) == topic->len) && memcmp(node->topic, topic->buffer, topic->len) == 0) {
            AIOT_LIST_FOR_EACH_ENTRY_SAFE(handler_node, handler_next, &node->handleList,linkedNode, MQTTSubHandlerNode) {
                if (handler_node->handler == handler) {
                    aiotListDel(&handler_node->linkedNode);
                    getSystemInterface()->memFree(handler_node);
                }
            }
        }
    }
}

void updateMqttSubList(MQTTEntity *entity, MQTTBuffer *topic, uint16_t packetId, uint8_t *packet, uint32_t len, uint8_t status, uint8_t type) {
    MQTTSubNode *node = NULL;
    AIOT_LIST_FOR_EACH_ENTRY(node, &entity->subList, linkedNode, MQTTSubNode) {
        if(type == 0) {
            if ((strlen(node->topic) == topic->len) && memcmp(node->topic, topic->buffer, topic->len) == 0) {
                node->packetId = packetId;
                SystemInterface* interface = getSystemInterface();
                if(node->packet) {
                    interface->memFree(node->packet);
                }

                node->packet = interface->memMalloc(len);   //如果失败如何处理
                if(node->packet) {
                    memset(node->packet, 0, len);
                    memcpy(node->packet, packet, len);
                    node->length = len;
                }
            }
        } else {
            if (node->packetId == packetId) {
                node->status = status;
            }
        }
    }
}

void resetAllMqttSubListStatus(MQTTEntity *entity) {
    MQTTSubNode *node = NULL;
    AIOT_LIST_FOR_EACH_ENTRY(node, &entity->subList, linkedNode, MQTTSubNode) {
        node->status = 0;
    }
}

int32_t insertMqttPubList(MQTTEntity *entity, uint8_t *packet, uint32_t len, uint16_t packetId) {

    MQTTPubNode *node = NULL;
    AIOT_LIST_FOR_EACH_ENTRY(node, &entity->pubList, linkedNode, MQTTPubNode) {
        if (node->packetId == packetId) {
            return mqttPublishPackIdRoll;
        }
    }

    node = getSystemInterface()->memMalloc(sizeof(MQTTPubNode));
    if (node == NULL) {
        return memoryMallocFailed;
    }

    memset(node, 0, sizeof(MQTTPubNode));
    initialAiotListHead(&node->linkedNode);
    node->packetId = packetId;
    node->packet = getSystemInterface()->memMalloc(len);
    if (node->packet == NULL) {
        getSystemInterface()->memFree(node);
        return memoryMallocFailed;
    }

    memset(node->packet, 0, len);
    memcpy(node->packet, packet, len);
    node->length = len;
    node->sendAt = getSystemInterface()->getTimestamp();

    aiotListAddTail(&node->linkedNode, &entity->pubList);
    return aiotSuccess;
}

void  removeMqttSubList(MQTTEntity *entity, MQTTBuffer *topic) {

    MQTTSubNode *node = NULL, *next = NULL;
    AIOT_LIST_FOR_EACH_ENTRY_SAFE(node, next, &entity->subList, linkedNode, MQTTSubNode) {
        if ((strlen(node->topic) == topic->len) && memcmp(node->topic, topic->buffer, topic->len) == 0) {
            aiotListDel(&node->linkedNode);
            destroyMqttSubListHandlerList(&node->handleList);
            getSystemInterface()->memFree(node->packet);
            getSystemInterface()->memFree(node->topic);
            getSystemInterface()->memFree(node);
        }
    }
}

int32_t insertMqttTopicAliasList(MQTTEntity *entity, MQTTBuffer *topic,uint16_t topicAlias, ListHead *list) {

    int32_t res = aiotSuccess;
    MQTTTopicAliasNode *node = NULL;
    AIOT_LIST_FOR_EACH_ENTRY(node, list, linkedNode,MQTTTopicAliasNode) {

        if ((strlen(node->topic) == topic->len) && memcmp(node->topic, topic->buffer, topic->len) == 0) {
            /** exist topic */
            return aiotSuccess;
        }
    }

    /** new topic */
    if (&node->linkedNode == list) {
        node = getSystemInterface()->memMalloc(sizeof(MQTTTopicAliasNode));
        if (node == NULL) {
            return memoryMallocFailed;
        }

        memset(node, 0, sizeof(MQTTTopicAliasNode));
        initialAiotListHead(&node->linkedNode);

        node->topic = getSystemInterface()->memMalloc(topic->len + 1);
        if (node->topic == NULL) {
            getSystemInterface()->memFree(node);
            return memoryMallocFailed;
        }

        memset(node->topic, 0, topic->len + 1);
        memcpy(node->topic, topic->buffer, topic->len);
        node->topicAlias = topicAlias;

        aiotListAddTail(&node->linkedNode, list);
    }

    return res;
}

void destroyMqttSubHandlerList(MQTTEntity *entity, ListHead *list) {

    MQTTSubHandlerNode *node = NULL, *next = NULL;

    AIOT_LIST_FOR_EACH_ENTRY_SAFE(node, next, list, linkedNode, MQTTSubHandlerNode) {
        aiotListDel(&node->linkedNode);
        getSystemInterface()->memFree(node);
    }
}

void removeMqttPubList(MQTTEntity *entity, uint16_t packetId) {

    MQTTPubNode *node = NULL, *next = NULL;
    AIOT_LIST_FOR_EACH_ENTRY_SAFE(node, next, &entity->pubList,linkedNode, MQTTPubNode) {

        if (node->packetId == packetId) {
            aiotListDel(&node->linkedNode);
            getSystemInterface()->memFree(node->packet);
            getSystemInterface()->memFree(node);
            return;
        }
    }
}

void appendMqttHandlerList(MQTTEntity *entity, ListHead *dest,ListHead *src, uint8_t *found) {

    MQTTSubHandlerNode *node = NULL, *copyNode = NULL;
    AIOT_LIST_FOR_EACH_ENTRY(node, src, linkedNode, MQTTSubHandlerNode) {
        copyNode = getSystemInterface()->memMalloc(sizeof(MQTTSubHandlerNode));
        if (copyNode == NULL) {
            continue;
        }

        memset(copyNode, 0, sizeof(MQTTSubHandlerNode));
        initialAiotListHead(&copyNode->linkedNode);
        copyNode->handler = node->handler;
        copyNode->context = node->context;

        aiotListAddTail(&copyNode->linkedNode, dest);
        *found = 1;
    }
}
